package com.bbtShop.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bbtShop.config.BizException;
import com.bbtShop.core.model.*;
import com.bbtShop.core.utils.Word2PdfUtil;
import com.bbtShop.core.utils.WordUtil;
import com.bbtShop.core.utils.dateToWeekUtil;
import com.bbtShop.dao.OfficeTableMapper;
import com.bbtShop.dao.UserMapper;
import com.google.common.math.IntMath;
import freemarker.template.TemplateException;
import io.swagger.models.auth.In;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;


/**
 * @Author manke
 * @Date 2020/10/14 14:00
 * @Version 0.0.1
 */
@Service
public class OfficeTableService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private OfficeTableMapper officeTableMapper;

    @Value("${path.url}")
    private String path;
    @Value("${path.baseUrl}")
    private String baseUrl;


    public void addPersonalOfficeTable(OfficeTableVo officeTableVo) {
        User user = userMapper.selectById(officeTableVo.getUserId());
        if (user == null) {
            throw new BizException("用户id不存在");
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String format = simpleDateFormat.format(officeTableVo.getRestDate());
        String[] split = format.split("-");
        int day = Integer.parseInt(split[2]); //获取当前月第几天休息
        int monthDays = getMonthDays(officeTableVo.getRestDate());    //计算当月天数
        if (day > monthDays) {
            throw new BizException("休息时间超出当前月份天数");
        }
        if (officeTableVo.getPeriod() > monthDays) {
            throw new BizException("上班周期不能超过本月天数");
        }
        //查询当前月份是否存在
        SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM");
        String format1 = simpleDateFormat1.format(officeTableVo.getRestDate());
        List<OfficeTable> officeTables = officeTableMapper.selectList(new LambdaQueryWrapper<OfficeTable>()
                .eq(OfficeTable::getUserId, user.getId()).like(OfficeTable::getDate, format1));
        if (officeTables.size() > 0) {
            throw new BizException("此用户当月排班已经添加");
        }
        //计算休息日期
        Map<String, String> job = getRestDate(user.getId() + "", user.getName(), day, officeTableVo.getPeriod(), monthDays);
        String jsonJob = JSONObject.toJSONString(job);
        OfficeTable officeTable = new OfficeTable();
        officeTable.setAddTime(new Date());
        officeTable.setDate(officeTableVo.getRestDate());
        officeTable.setName(user.getName());
        officeTable.setUserId(user.getId());
        officeTable.setTableData(jsonJob);
        officeTableMapper.insert(officeTable);

    }

    /**
     * @param userId    用户id
     * @param userName  用户名称
     * @param day       第几天休息
     * @param period    休息周期
     * @param monthDays 当前月份天数
     * @return
     */
    private Map<String, String> getRestDate(String userId, String userName, Integer day, Integer period, int monthDays) {
        int c = day % period; //获取最小休息日
        if (c == 0) {
            c = period;
        }
        LinkedHashMap<String, String> job = new LinkedHashMap<>();
        job.put("name", userName);
        job.put("userId", userId);
        for (int i = 1; i < monthDays + 1; i++) {
            int s = (i - c) % period;
            if (s == 0) {
                job.put("s" + i, "Ο");
            } else {
                job.put("s" + i, "√");
            }

        }
        return job;


    }

    //获取月份天数
    private Integer getMonthDays(Date date) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String format = simpleDateFormat.format(date);
        String[] split = format.split("-");
        String year = split[0];
        String month = split[1];

        if ("02".equals(month)) {
            //判断润平年
            int i = Integer.parseInt(year) % 4;
            if (i == 0) {
                //闰年
                return 29;

            } else {
                //平年
                return 28;
            }
        } else {
            if ("01".equals(month) || "03".equals(month) || "05".equals(month)
                    || "07".equals(month) || "08".equals(month) || "10".equals(month) || "12".equals(month)) {
                return 31;
            } else {
                return 30;
            }


        }

    }

    public String downloadOfficeTable(FileTableVo fileTableVo) throws IOException, TemplateException {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM");
        String format = simpleDateFormat.format(fileTableVo.getExportTime());
        String[] split = format.split("-");
        String ftlName = templateName(fileTableVo.getExportTime());
        String outFileName = format + "_No." + (int) (Math.random() * 1000) + "_job_table";

        ArrayList<Object> dates = new ArrayList<>();
        LinkedList<String> weeks = new LinkedList<>();
        String week = dateToWeekUtil.dateToWeek(format + "-" + "01");
        Integer num = weekToNum(week);
        int w=num;
        for (int i = 0; i < getMonthDays(fileTableVo.getExportTime()); i++) {
            dates.add(i);
            weeks.add(numToWeek(w));
            w++;
            if (w>7){
                w=1;
            }
        }
        //查询x月份
        List<OfficeTable> officeTables = officeTableMapper.selectList(new LambdaQueryWrapper<OfficeTable>().like(OfficeTable::getDate, format));
        if (officeTables.size() == 0) {
            throw new BizException("此月份没有任何人的排班数据");
        }

        HashMap<String, Object> map = new HashMap<>();
        ArrayList<Object> strings = new ArrayList<>();  //排班数据数组
        for (OfficeTable officeTable : officeTables) {
            String tableData = officeTable.getTableData();
            Map mapTypes = JSON.parseObject(tableData);
            strings.add(mapTypes);
        }
        map.put("year", split[0]);
        map.put("month", split[1]);
        map.put("list", strings);
        map.put("dates", dates);
        map.put("weeks",weeks);
        WordUtil.testPaperWord(map, path, ftlName, outFileName + ".docx");
        return baseUrl + outFileName + ".docx";
    }

    private String numToWeek(Integer num){
        return getString(num);

    }

    private String getString(Integer num) {
        switch (num){
            case 1:
                return "一";
            case 2:
                return "二";
            case 3:
                return "三";
            case 4:
                return "四";
            case 5:
                return "五";
            case 6:
                return "六";
            case 7:
                return "日";
        }
        return null;
    }

    private Integer weekToNum(String week){
        switch (week){
            case "一":
                return 1;
            case "二":
                return 2;
            case "三":
                return 3;
            case "四":
                return 4;
            case "五":
                return 5;
            case "六":
                return 6;
            case "日":
                return 7;
        }
        return null;

    }

    private String templateName(Date date) {
        Integer monthDays = getMonthDays(date);
        return "job" + monthDays + ".ftl";
    }

    public IPage<OfficeTable> getListOfficeTable(Integer pageNum, Integer pageSize, OfficeTable officeTable) {
        IPage<OfficeTable> page = new Page<>(pageNum == null ? 1 : pageNum,
                pageSize == null ? 10 : pageSize);
        LambdaQueryWrapper<OfficeTable> officeTableLambdaQueryWrapper = new LambdaQueryWrapper<>();
        if (officeTable.getName()!=null&&!officeTable.getName().isEmpty()){
            officeTableLambdaQueryWrapper.like(OfficeTable::getName,officeTable.getName());
        }
        if (officeTable.getDate()!=null){
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            String format = simpleDateFormat.format(officeTable.getDate());
            String substring = format.substring(0, 7);
            officeTableLambdaQueryWrapper.like(OfficeTable::getDate,substring);
        }
        return officeTableMapper.selectPage(page,officeTableLambdaQueryWrapper);
    }

    public void delOfficeTable(Ids ids) {
        officeTableMapper.deleteBatchIds(ids.getIds());
    }

    public void updateOfficeTable(UpdOfficeTableVo updOfficeTableVo) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String format = simpleDateFormat.format(updOfficeTableVo.getDate());
        String day = format.split("-")[2];
        String parameter = "s"+day;
        if (Integer.parseInt(day) < 10) {
            String replace = day.replace("0", "");
            parameter="s"+replace;
        }

        OfficeTable officeTable = officeTableMapper.selectById(updOfficeTableVo.getId());
        String tableData = officeTable.getTableData();
        Map map = JSON.parseObject(tableData);
        map.put(parameter, updOfficeTableVo.getState().equals("1")?"√":"Ο");
        officeTable.setTableData(JSONObject.toJSONString(map));
        officeTableMapper.updateById(officeTable);
    }

    public List<OfficeTableInfoDto> getOfficeTableInfo(Integer id) {
        OfficeTable officeTable = officeTableMapper.selectById(id);
        Date date = officeTable.getDate();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String format = simpleDateFormat.format(date);
        String[] split = format.split("-");

        String tableData = officeTable.getTableData();
        Map map = JSON.parseObject(tableData);
        map.remove("userId");
        map.remove("name");
        ArrayList<OfficeTableInfoDto> officeTableInfoDtos = new ArrayList<>();
        for (Object key : map.keySet()) {//keySet获取map集合key的集合  然后在遍历key即可
            OfficeTableInfoDto officeTableInfoDto = new OfficeTableInfoDto();
            String s = String.valueOf(key).replace("s", "");
            if (Integer.parseInt(s) < 10) {
                s = "0" + s;
            }
            String value = map.get(key).toString();//
            if (value.equals("√")){
                officeTableInfoDto.setData("班");
            }
            if (value.equals("Ο")){
                officeTableInfoDto.setData("休");
            }
            officeTableInfoDto.setStyle(value.equals("√") ? "color: #F56C6C" : "color: #00a854");
            officeTableInfoDto.setTime(split[0] + "-" + split[1] + "-" + s);
            officeTableInfoDtos.add(officeTableInfoDto);
        }
        return officeTableInfoDtos;

    }

    public String getJobState(JobStateVo jobStateVo) {
        Map<String, Object> officeTableMap = getOfficeTableMap(jobStateVo.getId());
        String day = dateChangeDay(jobStateVo.getDate()); //时间转换天
        return (officeTableMap.get("s" + day)).equals("√")?"1":"2";
    }

    private Map<String, Object> getOfficeTableMap(Integer id) {
        OfficeTable officeTable = officeTableMapper.selectById(id);
        String tableData = officeTable.getTableData();
        Map<String, Object> map = JSON.parseObject(tableData);
        map.remove("name");
        map.remove("userId");
        return map;

    }

    private String dateChangeDay(Date date) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String format = simpleDateFormat.format(date);
        String day = format.split("-")[2];
        if (Integer.parseInt(day) < 10) {
            return day.replace("0", "");
        }
        return day;
    }
}
